[% setvar title Change the way $SIG{__WARN__} and $SIG{__DIE__} are used %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='TITLE'></a><h1>TITLE</h1>
<p>Change the way $SIG{__WARN__} and $SIG{__DIE__} are used</p>
<a name='VERSION'></a><h1>VERSION</h1>
<pre>  Maintainer: Chris Hostetter &lt;<a href='mailto:chrish@cnet.com'>chrish@cnet.com</a>&gt;
  Date: 15 Sep 2000
  Mailing List: <a href='mailto:perl6-language@perl.org'>perl6-language@perl.org</a>
  Number: 236
  Version: 1
  Status: Developing</pre>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>The current method in which <code>__WARN__</code> and <code>__DIE__</code> signal handlers are
used is limited in 2ways:</p>
<ul>
<li><a name='It does not allow them to accept robust parameter lists.'></a>It does not allow them to accept robust parameter lists.</li>
<li><a name='It does not allow for multiple layers of handlers.'></a>It does not allow for multiple layers of handlers.</li>
</ul>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<a name='Parameter Treatment'></a><h2>Parameter Treatment</h2>
<p>The current behavior of <code>warn</code> and <code>die</code> is to first concatenate the
parameter LIST into a single string, before checking if there is a
user specified signal handler.  Then pass that string as a single
argument to any handler if it exists.</p>
<p>I propose, that a registered signal handler for <code>__WARN__</code> or <code>__DIE__</code>
should be passed the exact same LIST of arguments that the
corresponding warn or die call received.  This would allow complex
programs to use the warn/die signal handling mechanism to for dealing
with complex exception handling, and still recognize low level
warnings / errors from the interpreter.</p>
<p>For example: It is reasonable when developing a large system to want a
mechanism for dealing with &quot;error levels&quot; -- one such approach would
be something like the following...</p>
<pre>	# use this function EXCLUSIVELY in your code for dealing with
	# warnings or errors so that the appropraite acction is taken
	sub errorHandle {
		my $level = shift;
		my @msgs = @_;
		if ($config{abort_level} &lt; $level) {
			die &quot;Fatal Error ($level): &quot;, @msgs;
		} 
		if ($config{warn_level} &lt; $level) {
			warn &quot;Warning ($level): &quot;, @msgs;
		}
		if ($config{log_level} &lt; $level) {
			# log something about @msgs
		}
		# etc ...
	}

	# want to make sure we catch things from interpreter and
	# code from CPAN
	$SIG{__WARN__} = sub { &amp;errorHandler(9,  @_); }
	$SIG{__DIE__} =  sub { &amp;errorHandler(11, @_); }

	# ...

	&amp;validateSomething($someArg) or errorHandle 9, &quot;couldn't validate&quot;;</pre>
<p>The problem with this, is that it requires you to use the non standard
&quot;errorHandle&quot; function explicitly in your code.  If you are writing a
module that you plan on distributing to others, this is not ideal.</p>
<p>This would be far better, but would require that <code>$SIG{__WARN__}</code>
(and <code>$SIG{__DIE__}</code>) received the same list of parameters that warn (and
die) received...</p>
<pre>	# want to make sure we catch things from our code, the
	# interpreter, or code from CPAN
	$SIG{__WARN__} = sub {
		my $level = $config{default_warn_level};
		(1 &lt; scalar(@_)) ? $level = shift;
		my @msgs = @_;
		if ($config{abort_level} &lt; $level) {
			die &quot;Fatal Error ($level): &quot;, @msgs;
		} 
		if ($config{warn_level} &lt; $level) {
			warn &quot;Warning ($level): &quot;, @msgs;
		}
		if ($config{log_level} &lt; $level) {
			# log something about @msgs
		}
		# etc ...
	}
	$SIG{__DIE__} =  sub { warn $config{default_warn_level}, @_; }

	# ...

	&amp;validateSomething($someArg) or warn 9, &quot;couldn't validate&quot;;</pre>
<a name='Nested Handlers'></a><h2>Nested Handlers</h2>
<p>Currently, if a handler is called to deal with <code>$SIG{__WARN__}</code> or
<code>$SIG{__DIE__}</code> then the handler is disabled to prevent infinite
recursion if the handler itself calls <code>die</code> or <code>warn</code>.</p>
<p>It seems only logical, that if the current handler has been localized,
and overshadows an outer handler, then calling <code>warn</code> or <code>die</code> should
invoke the outer handler -- not the real <code>warn</code> or <code>die</code>.  For example...</p>
<pre>	#!/usr/local/bin/perl -w
	$SIG{__WARN__} = sub { print &quot;outer handler: &quot;, @_; };

	sub bar {
	    warn &quot;in bar&quot;;
	}
	
	sub foo {
	    local $SIG{__WARN__} = sub { warn &quot;foo: &quot;, @_; };
	    &amp;bar();
	}

	&amp;foo();</pre>
<p>... this script causes &quot;<code>foo: in bar at warn.test.pl line 6.</code>&quot; to be
written to standard error.  I propose that &quot;<code>outer handler: foo: in bar
at warn.test.pl line 6.</code>&quot; is more logical output.</p>
<p>This would allow modules to do their own <code>__WARN__</code> and <code>__DIE__</code> handling,
but still propagate the messages out to an application specific
handler.</p>
<a name='IMPLEMENTATION'></a><h1>IMPLEMENTATION</h1>
<p>Unknown.</p>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<p>Programming Perl, 2nd Ed -- p139</p>
<p>Programming Perl, 2nd Ed -- p157</p>
<p>Programming Perl, 2nd Ed -- p241</p>
</div>
